package org.liveboardgames.agricola.business.updater;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.liveboardgames.agricola.business.helper.GameHelper;
import org.liveboardgames.agricola.domain.Change;
import org.liveboardgames.agricola.domain.Game;
import org.liveboardgames.agricola.domain.board.BoardTile;
import org.liveboardgames.agricola.domain.card.ActionCard;
import org.liveboardgames.agricola.domain.card.Card;
import org.liveboardgames.agricola.domain.card.ImprovementCard;
import org.liveboardgames.agricola.domain.common.Peep;
import org.liveboardgames.agricola.domain.player.Player;
import org.liveboardgames.agricola.model.enums.ChangesEnum;

public class GameUpdater extends AbstractUpdater {

  private Game game;

  public GameUpdater(Game game, List<Change> changes) {
    super(changes);
    this.game = game;
  }

  public void sendAllPeepsHome() {

    GameHelper gameHelper = new GameHelper();
    List<Card> playedCards = gameHelper.getAllPlayedCards(game);

    for (Iterator<Card> iterator = playedCards.iterator(); iterator.hasNext();) {
      Card card = iterator.next();

      Set<Peep> peeps = card.getPeeps();

      if (peeps != null && peeps.size() > 0) {

        for (Iterator<Peep> iterator2 = peeps.iterator(); iterator2.hasNext();) {
          Peep peep = iterator2.next();
          Player owner = gameHelper.getPeepOwner(game, peep);
          new FarmUpdater(game, owner.getFarm(), getChanges()).addPeep(peep);
        }
        new CardUpdater(card, getChanges()).removePeeps();
      }
    }
  }

  public void growUpPeeps() {
    List<Player> players = game.getPlayers();

    for (Iterator<Player> iterator = players.iterator(); iterator.hasNext();) {
      Player player = (Player)iterator.next();
      new FarmUpdater(game, player.getFarm(), getChanges()).growUpPeeps();
    }
  }

  public void addNextActionCard() {
    // Get the next card in the waiting list
    List<ActionCard> waitingActionCards = game.getWaitingActionCards();
    if (waitingActionCards != null && waitingActionCards.size() > 0) {

      ActionCard actionCard = waitingActionCards.remove(0);

      Change change = new Change(ChangesEnum.WAITING_ACTIONS, waitingActionCards);
      addChange(change);

      // Find the first tile (in the season tiles) that has no action card
      // attached
      BoardTile firstEmptySeasonTile = new GameHelper().findFirstEmptySeasonTile(game);

      if (firstEmptySeasonTile != null) {
        new BoardTileUpdater(firstEmptySeasonTile, getChanges()).updateActionCard(actionCard);
      }
    }
  }

  public void setCurrentPlayer(Player player) {
    game.setCurrentPlayer(player);
    Change change = new Change(ChangesEnum.CURRENT_PLAYER, player.getId());
    addChange(change);
  }

  public void setHasPlayerPlayedPeep(boolean hasPlayerPlayedPeep) {
    game.setHasPlayerPlayedPeep(hasPlayerPlayedPeep);
    Change change = new Change(ChangesEnum.PLAYER_PLAYED_PEEP, hasPlayerPlayedPeep);
    addChange(change);
  }

  public void addMajorImprovement(ImprovementCard improvement) {
    game.getMajorImprovements().add(improvement);
    Change change = new Change(ChangesEnum.ADD_MAJOR_IMPROVEMENT, improvement);
    addChange(change);
  }

  public void removeImprovement(ImprovementCard improvement) {
    game.getMajorImprovements().remove(improvement);
    Change change = new Change(ChangesEnum.REMOVE_MAJOR_IMPROVEMENT, improvement.getCardId());
    addChange(change);
  }

  public void resetHarvest() {
    game.setHarvestFieldPlayers(new HashSet<Player>());
    game.setHarvestFeedPlayers(new HashSet<Player>());
    game.setHarvestBreedPlayers(new HashSet<Player>());
    Change change = new Change(ChangesEnum.RESET_HARVEST, null);
    addChange(change);
  }

  public void addHarvestFeedPlayer(Player player) {
    game.addHarvestFeedPlayer(player);
    Change change = new Change(ChangesEnum.HARVEST_FEED_NEW, player.getId());
    addChange(change);
  }

  public void addHarvestFieldPlayer(Player player) {
    game.addHarvestFieldPlayer(player);
    Change change = new Change(ChangesEnum.HARVEST_FIELD_NEW, player.getId());
    addChange(change);
  }

  public void addHarvestBreedPlayer(Player player) {
    game.addHarvestBreedPlayer(player);
    Change change = new Change(ChangesEnum.HARVEST_BREED_NEW, player.getId());
    addChange(change);
  }

  public void updateEndGame() {
    game.setIsFinished(true);
    Change change = new Change(ChangesEnum.GAME_FINISHED, game.getIsFinished());
    addChange(change);
  }

}
